home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-12-08 | 37.3 KB | 1,048 lines |
- //========================================================================================
- //
- // File: ContainerLink.cpp
- // Release Version: $ 1.0d11 $
- //
- // Author: Henri Lamiraux
- // Linking added by: M.Boetcher
- //
- // Copyright: © 1993, 1995 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "Container.hpp"
-
- #ifndef CONTAINERLINK_H
- #include "ContainerLink.h"
- #endif
-
- #ifndef CONTAINERDEF_H
- #include "ContainerDef.h"
- #endif
-
- #ifndef CONTAINERPART_H
- #include "ContainerPart.h"
- #endif
-
- #ifndef CONTAINERSEL_H
- #include "ContainerSel.h"
- #endif
-
- #ifndef BASESHP_H
- #include "BaseShp.h"
- #endif
-
- #ifndef BOUNDSHP_H
- #include "BoundShp.h"
- #endif
-
- #ifndef LINESHP_H
- #include "LineShp.h"
- #endif
-
- #ifndef OVALSHP_H
- #include "OvalShp.h"
- #endif
-
- #ifndef RECTSHP_H
- #include "RectShp.h"
- #endif
-
- #ifndef RRECTSHP_H
- #include "RRectShp.h"
- #endif
-
- #ifndef TEXTSHP_H
- #include "TextShp.h"
- #endif
-
- #ifndef CONTAINERPRXY_H
- #include "ContainerPrxy.h"
- #endif
-
- // ----- Framework Includes -----
-
- #ifndef FWFRAME_H
- #include "FWFrame.h"
- #endif
-
- #ifndef FWITERS_H
- #include "FWIters.h"
- #endif
-
- #ifndef FWPRTITE_H
- #include "FWPrtIte.h"
- #endif
-
- #ifndef FWPRESEN_H
- #include "FWPresen.h"
- #endif
-
- #ifndef FWPXYFRM_H
- #include "FWPxyFrm.h"
- #endif
-
- #ifndef FWUTIL_H
- #include "FWUtil.h"
- #endif
-
- #ifndef FWCLNINF_H
- #include "FWClnInf.h"
- #endif
-
- #ifndef FWBARRAY_H
- #include "FWBArray.h"
- #endif
-
- // ----- Foundation Includes -----
-
- #ifndef FWORDCOL_H
- #include "FWOrdCol.h"
- #endif
-
- #ifndef FWMEMMGR_H
- #include "FWMemMgr.h"
- #endif
-
- // ----- OpenDoc Includes -----
-
- #ifndef SOM_Module_OpenDoc_StdProps_defined
- #include <StdProps.xh>
- #endif
-
- #ifndef SOM_Module_OpenDoc_StdTypes_defined
- #include <StdTypes.xh>
- #endif
-
- #ifndef SOM_ODStorageUnit_xh
- #include <StorageU.xh>
- #endif
-
- #ifndef SOM_ODUndo_xh
- #include <Undo.xh>
- #endif
-
- #ifndef SOM_ODSession_xh
- #include <ODSessn.xh>
- #endif
-
- #ifndef SOM_ODLink_xh
- #include <Link.xh>
- #endif
-
- #ifndef SOM_ODLinkSpec_xh
- #include <LinkSpec.xh>
- #endif
-
- #ifndef SOM_ODLinkSource_xh
- #include <LinkSrc.xh>
- #endif
-
- //========================================================================================
- // Runtime Information
- //========================================================================================
-
- FW_DEFINE_CLASS_M1(CContainerPublishLink, FW_CPublishLink)
- FW_DEFINE_CLASS_M1(CContainerSubscribeLink, FW_CSubscribeLink)
-
- #ifdef FW_BUILD_MAC
- #pragma segment container
- #endif
-
- //========================================================================================
- // Constants
- //========================================================================================
-
- const ODPropertyName kContainerPropSourceLink = "Container:Property:SourceLink";
- const ODPropertyName kContainerPropDestLink = "Container:Property:DestLink";
-
- const ODValueType kContainerLinkValue = "Container:Value";
-
- //========================================================================================
- // class CContainerPublishLink
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // CContainerPublishLink::CContainerPublishLink
- //----------------------------------------------------------------------------------------
-
- CContainerPublishLink::CContainerPublishLink(Environment *ev, ODUpdateID updateID,
- FW_CPresentation* presentation,
- CContainerSelection* containerSelection,
- FW_Boolean saveSelection) :
- FW_CPublishLink(ev, updateID, presentation),
- fContainerSelection(containerSelection),
- fCollection(NULL),
- fSavedSelection(NULL)
- {
- //---- Create a new collection to hold the shapes in this link source ----
- fCollection = new FW_CPrivOrderedCollection;
-
- //---- Save the selected shapes ----
- if (saveSelection)
- {
- FW_COrderedCollectionIterator ite(fContainerSelection->GetSelectionCollection());
- for (CBaseShape* shape = (CBaseShape*)ite.First(); ite.IsNotComplete(); shape = (CBaseShape*)ite.Next())
- {
- fCollection->AddLast(shape);
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerPublishLink::~CContainerPublishLink
- //----------------------------------------------------------------------------------------
-
- CContainerPublishLink::~CContainerPublishLink()
- {
- delete fCollection;
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerPublishLink::Publish - Override
- //----------------------------------------------------------------------------------------
-
- void CContainerPublishLink::Publish(Environment* ev)
- {
- //---- Mark the collected shapes as published
- FW_COrderedCollectionIterator ite(fCollection);
- for (CBaseShape* shape = (CBaseShape*)ite.First(); ite.IsNotComplete(); shape = (CBaseShape*)ite.Next())
- {
- shape->SetPublishLink(ev, this);
- }
-
- //--- Force the first update using a new change ID
- ODUpdateID change = fPresentation->GetPart(ev)->GetSession(ev)->UniqueUpdateID(ev);
- this->ContentUpdated(ev, change, TRUE);
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerPublishLink::GetPublishFormat - Override
- //----------------------------------------------------------------------------------------
-
- ODValueType CContainerPublishLink::GetPublishFormat(Environment* ev)
- {
- return kPublishFormat;
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerPublishLink::ExternalizeLinkContent - Override
- //----------------------------------------------------------------------------------------
-
- void CContainerPublishLink::ExternalizeLinkContent(Environment* ev, ODStorageUnit* linkSU)
- {
- // Remove extra properties (ODLinkSource::Clear removed only the content property)
- FW_SURemoveProperty(ev, linkSU, kODPropContentFrame);
-
- // -- Pick a frame, any frame --
- FW_CPresentationFrameIterator piter(fPresentation);
- FW_CFrame* frame = piter.First();
- FW_ASSERT(frame);
-
- // Since ExternalizeData writes the current selection,
- // we need to temporarily select the shapes to be published
- this->SelectShapes(ev);
-
- fContainerSelection->ExternalizeData(ev, frame, FW_kLinkStorage, linkSU, kODCloneToLink);
-
- // Now restore the saved selection
- this->RestoreContainerSelection(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerPublishLink::SelectShapes
- //----------------------------------------------------------------------------------------
- void CContainerPublishLink::SelectShapes(Environment* ev)
- {
- // Save the list of selected shapes
- fSavedSelection = fContainerSelection->GetSelectionCollection();
- fContainerSelection->CloseSelection(ev); // empty the selection
-
- // Add all our published shapes to the selection
- FW_COrderedCollectionIterator iter(fCollection);
- for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
- {
- fContainerSelection->AddToSelection(ev, shape, FALSE);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerPublishLink::RestoreContainerSelection
- //----------------------------------------------------------------------------------------
- void CContainerPublishLink::RestoreContainerSelection(Environment* ev)
- {
- fContainerSelection->CloseSelection(ev); // empty the selection
-
- // Add the saved shapes to the selection
- FW_COrderedCollectionIterator iter(fSavedSelection);
- for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
- {
- fContainerSelection->AddToSelection(ev, shape, FALSE);
- }
- fSavedSelection = NULL;
-
- // Recontainer???
- fPresentation->Invalidate(ev); // force all frames to be recontainern
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerPublishLink::HasEmbeddedFrame
- //----------------------------------------------------------------------------------------
- FW_Boolean CContainerPublishLink::HasEmbeddedFrame(Environment *ev, ODFrame* odFrame)
- {
- // Is odFrame involved in this link source? (called by DoUpdateLinks)
-
- // --- Find out whether odFrame is involved in any link source ---
- if (odFrame->GetLinkStatus(ev) == kODInLinkSource)
- {
- // -- Find out whether odFrame is one of my frames --
- FW_CFrame* fwFrame = FW_CFrame::ODtoFWFrame(ev, odFrame);
- if (fwFrame)
- {
- FW_COrderedCollectionIterator iter(fCollection);
- for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
- {
- if ((shape->GetShapeType() == kProxyShape) && (((CProxyShape*)shape)->IsEmbeddedFrame(ev, odFrame)))
- return TRUE;
- }
- }
- }
-
- return FALSE;
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerPublishLink::GetFrameToRevealLink
- //----------------------------------------------------------------------------------------
- FW_CFrame* CContainerPublishLink::GetFrameToRevealLink(Environment* ev)
- {
- // Just return the presentation's first display frame
- FW_CPresentationFrameIterator piter(fPresentation);
- return piter.First();
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerPublishLink::DoSelect
- //----------------------------------------------------------------------------------------
- void CContainerPublishLink::DoSelect(Environment* ev, FW_CFrame* /*frame*/)
- {
- fContainerSelection->CloseSelection(ev); // empty the selection
-
- // Add all our published shapes to the selection
- FW_COrderedCollectionIterator iter(fCollection);
- for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
- {
- fContainerSelection->AddToSelection(ev, shape, TRUE); // container selection handles
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerPublishLink::AddShape
- //----------------------------------------------------------------------------------------
- void CContainerPublishLink::AddShape(Environment* ev, CBaseShape* shape)
- {
- shape->SetPublishLink(ev, this);
- fCollection->AddLast(shape);
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerPublishLink::Externalize
- //----------------------------------------------------------------------------------------
-
- void CContainerPublishLink::Externalize(Environment* ev, ODStorageUnit* storageUnit,
- FW_CCloneInfo* cloneInfo)
- {
- //-- Storage unit must be focussed to property kContainerPropDestLink, value containerPartValueType
- fODLinkSource->Externalize(ev);
-
- ODID linkID = fODLinkSource->GetID(ev);
- if (cloneInfo != NULL)
- {
- linkID = cloneInfo->Clone(ev, linkID, 0, 0);
- }
- FW_ASSERT(linkID != kODNULL);
-
- //--- Write a reference to the link ---
- ODStorageUnitRef suRef;
- storageUnit->GetStrongStorageUnitRef(ev, linkID, suRef);
- FW_CByteArray byteArray(&suRef, sizeof(ODStorageUnitRef));
- storageUnit->SetValue(ev, byteArray);
-
- //--- Write update ID ---
- byteArray.Set(&fUpdateID, sizeof(ODUpdateID));
- storageUnit->SetValue(ev, byteArray);
-
- //--- Write the number of shapes in the link ---
- unsigned long shapeCount = fCollection->Count();
- FW_ASSERT(shapeCount != 0);
- byteArray.Set(&shapeCount, sizeof(unsigned long));
- storageUnit->SetValue(ev, byteArray);
-
- //--- Write the externalization index for each shape in the link ---
- FW_COrderedCollectionIterator iter(fCollection);
- for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
- {
- short extIndex = shape->GetExternalizationIndex();
- byteArray.Set(&extIndex, sizeof(short));
- storageUnit->SetValue(ev, byteArray);
- }
- }
-
- //========================================================================================
- // class CContainerSubscribeLink
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // CContainerSubscribeLink::CContainerSubscribeLink
- //----------------------------------------------------------------------------------------
-
- CContainerSubscribeLink::CContainerSubscribeLink(Environment* ev, ODLink* odLink,
- FW_CPresentation* presentation,
- CContainerSelection* containerSelection,
- ODLinkInfo* linkInfo) :
- FW_CSubscribeLink(ev, odLink, linkInfo, presentation),
- fContainerSelection(containerSelection),
- fCollection(NULL),
- fSavedSelection(NULL)
- {
- fUpdateOffset.Clear();
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerSubscribeLink::~CContainerSubscribeLink
- //----------------------------------------------------------------------------------------
-
- CContainerSubscribeLink::~CContainerSubscribeLink()
- {
- delete fCollection;
- }
-
- //---------------------------------------------------------------------------------------
- // CContainerSubscribeLink::Subscribe - Override
- //---------------------------------------------------------------------------------------
-
- void CContainerSubscribeLink::Subscribe(Environment* ev)
- {
- // SetCollection already initialized fCollection (called from DoUpdateLink)
- }
-
- //---------------------------------------------------------------------------------------
- // CContainerSubscribeLink::DoUpdateLink - Override
- //---------------------------------------------------------------------------------------
-
- void CContainerSubscribeLink::DoUpdateLink(Environment* ev, ODStorageUnit* linkContentSU)
- {
- // Read data from the linkContentSU
- FW_CPresentationFrameIterator piter(fPresentation);
- FW_CFrame* frame = piter.First();
- FW_ASSERT(frame);
-
- // Since InternalizeData reads into the current selection,
- // we need to save the selection and clear the linked shapes before reading new ones
- this->SaveAndSelectShapes(ev);
-
- fContainerSelection->InternalizeData(ev, frame, linkContentSU, kODCloneFromLink);
- this->SetCollection(ev);
-
- // Now restore the saved selection
- this->RestoreContainerSelection(ev);
-
- fPresentation->Invalidate(ev); // force all frames to be recontainern
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerSubscribeLink::SetCollection
- //----------------------------------------------------------------------------------------
- void CContainerSubscribeLink::SetCollection(Environment *ev)
- {
- FW_Boolean updating = (fCollection != NULL);
- if (fCollection)
- this->EmptyCollection(ev);
- else
- fCollection = new FW_CPrivOrderedCollection;
-
- FW_COrderedCollectionIterator ite(fContainerSelection->GetSelectionCollection());
- for (CBaseShape *shape = (CBaseShape*)ite.First(); ite.IsNotComplete(); shape = (CBaseShape*)ite.Next())
- {
- shape->SetSubscribeLink(ev, this);
- fCollection->AddLast(shape);
- }
-
- if (updating && fUpdateOffset != FW_kZeroPoint) // updating an existing link
- {
- // move the updated shapes to their proper position
- FW_CRect selRect;
- fContainerSelection->GetDragRect(selRect);
- fContainerSelection->OffsetSelection(ev, fUpdateOffset.x - selRect.left, fUpdateOffset.y - selRect.top);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerSubscribeLink::SelectShapes
- //----------------------------------------------------------------------------------------
- void CContainerSubscribeLink::SelectShapes(Environment* ev)
- {
- fContainerSelection->CloseSelection(ev); // empty the selection
-
- // Add all our subscribed shapes to the selection
- FW_COrderedCollectionIterator iter(fCollection);
- for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
- {
- fContainerSelection->AddToSelection(ev, shape, FALSE);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerSubscribeLink::SaveAndSelectShapes
- //----------------------------------------------------------------------------------------
- void CContainerSubscribeLink::SaveAndSelectShapes(Environment* ev)
- {
- // Save the list of selected shapes
- fSavedSelection = fContainerSelection->GetSelectionCollection();
- fContainerSelection->CloseSelection(ev); // empty the selection
-
- if (!fCollection) return; // fCollection is NULL when it's the first update
-
- // Add all our subscribed shapes to the selection so we can delete them
- FW_COrderedCollectionIterator iter(fCollection);
- for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
- {
- fContainerSelection->AddToSelection(ev, shape, FALSE);
- }
-
- // Save the selection's position
- FW_CRect tempRect;
- fContainerSelection->GetDragRect(tempRect);
- fUpdateOffset = tempRect.TopLeft();
-
- // Before deleting the link destination shapes, clear the Undo stacks to get rid of
- // any references to these doomed shapes.
- ODUndo* undo = fPresentation->GetPart(ev)->GetSession(ev)->GetUndo(ev);
- undo->ClearActionHistory(ev, kODDontRespectMarks); // dis 'em
-
- // Delete the link destination shapes; they'll be recreated when the link is updated
- fContainerSelection->DeleteSelection(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerSubscribeLink::RestoreContainerSelection
- //----------------------------------------------------------------------------------------
- void CContainerSubscribeLink::RestoreContainerSelection(Environment* ev)
- {
- fContainerSelection->CloseSelection(ev); // empty the selection
-
- // Add the saved shapes to the selection
- FW_COrderedCollectionIterator iter(fSavedSelection);
- for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
- {
- fContainerSelection->AddToSelection(ev, shape, FALSE);
- }
- fSavedSelection = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerSubscribeLink::EmptyCollection
- //----------------------------------------------------------------------------------------
- void CContainerSubscribeLink::EmptyCollection(Environment* ev)
- {
- if (fCollection)
- {
- fCollection->RemoveAll();
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerSubscribeLink::BreakLink - Override
- //----------------------------------------------------------------------------------------
- void CContainerSubscribeLink::BreakLink(Environment* ev)
- {
- FW_CSubscribeLink::BreakLink(ev);
-
- //--- Erase Link Borders ---
- fPresentation->Invalidate(ev); // force all frames to be recontainern
-
- //--- Change status of embedded frames ---
- FW_COrderedCollectionIterator ite(fCollection);
- for (CBaseShape* shape = (CBaseShape*)ite.First(); ite.IsNotComplete(); shape = (CBaseShape*)ite.Next())
- {
- if (shape->GetShapeType() == kProxyShape)
- ((CProxyShape*)shape)->ChangeLinkStatus(ev, kODNotInLink);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerSubscribeLink::AddShape
- //----------------------------------------------------------------------------------------
- void CContainerSubscribeLink::AddShape(Environment* ev, CBaseShape* shape)
- {
- shape->SetSubscribeLink(ev, this);
- if (fCollection == NULL)
- fCollection = new FW_CPrivOrderedCollection;
- fCollection->AddLast(shape);
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerSubscribeLink::Externalize
- //----------------------------------------------------------------------------------------
-
- void CContainerSubscribeLink::Externalize(Environment* ev, ODStorageUnit* storageUnit,
- FW_CCloneInfo* cloneInfo)
- {
- //-- Storage unit must be focused to property kContainerPropDestLink, value containerPartValueType
- fODLink->Externalize(ev);
-
- ODID linkID = fODLink->GetID(ev);
- if (cloneInfo != NULL)
- {
- linkID = cloneInfo->Clone(ev, linkID, 0, 0);
- }
- FW_ASSERT(linkID != kODNULL);
-
- //--- Write a reference to the link ---
- ODStorageUnitRef suRef;
- storageUnit->GetStrongStorageUnitRef(ev, linkID, suRef);
- FW_CByteArray byteArray(&suRef, sizeof(ODStorageUnitRef));
- storageUnit->SetValue(ev, byteArray);
-
- //--- Write link info ---
- ODType kind = fLinkInfo.kind; // save kind string
- fLinkInfo.kind = (ODType) strlen(kind) + 1; // stash its length in linkInfo
- byteArray.Set(&fLinkInfo, sizeof(ODLinkInfo));
- storageUnit->SetValue(ev, byteArray); // write out linkInfo
- byteArray.Set((void*)kind, (ODULong)fLinkInfo.kind);
- storageUnit->SetValue(ev, byteArray); // write out kind string
- fLinkInfo.kind = kind; // restore kind string
-
- //--- Write the number of shapes in the link ---
- unsigned long shapeCount = fCollection->Count();
- FW_ASSERT(shapeCount != 0);
- byteArray.Set(&shapeCount, sizeof(unsigned long));
- storageUnit->SetValue(ev, byteArray);
-
- //--- Write the export index for each shape in the link ---
- FW_COrderedCollectionIterator iter(fCollection);
- for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
- {
- short extIndex = shape->GetExternalizationIndex();
- byteArray.Set(&extIndex, sizeof(short));
- storageUnit->SetValue(ev, byteArray);
- }
- }
-
- //========================================================================================
- // class CContainerLinkManager
- //========================================================================================
-
- FW_DEFINE_CLASS_M1(CContainerLinkManager, FW_CLinkManager)
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager constructor
- //----------------------------------------------------------------------------------------
-
- CContainerLinkManager::CContainerLinkManager(Environment* ev, CContainerPart* thePart) :
- FW_CLinkManager(ev, (FW_CPart*)thePart),
- fContainerPart(thePart)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager destructor
- //----------------------------------------------------------------------------------------
-
- CContainerLinkManager::~CContainerLinkManager()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::NewPublishLink - Override
- //----------------------------------------------------------------------------------------
-
- FW_CPublishLink* CContainerLinkManager::NewPublishLink(Environment* ev, ODUpdateID changeID,
- FW_CPresentation* presentation)
- {
- return new CContainerPublishLink(ev, changeID,
- presentation, fContainerPart->fContainerSelection,
- TRUE); // saveSelection = TRUE
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::NewSubscribeLink - Override
- //----------------------------------------------------------------------------------------
-
- FW_CSubscribeLink* CContainerLinkManager::NewSubscribeLink(Environment* ev, ODLink *odLink,
- ODLinkInfo* linkInfo,
- FW_CPresentation* presentation)
- {
- return new CContainerSubscribeLink(ev, odLink, presentation, fContainerPart->fContainerSelection, linkInfo);
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::DoChangeLinkStatus - Override
- //----------------------------------------------------------------------------------------
-
- void CContainerLinkManager::DoChangeLinkStatus(Environment* ev, ODFrame* odFrame)
- {
- // call ODFrame::ChangeLinkStatus on any embedded frames that are involved in a link
- // when a link is created, broken, moved, etc.
- // odFrame is the frame of this part whose link status has changed.
-
- FW_CEmbeddingFrame* frame = FW_CEmbeddingFrame::ODtoFWEmbeddingFrame(ev, odFrame);
- if (frame)
- {
- ODLinkStatus linkStatus = odFrame->GetLinkStatus(ev);
-
- // Only need to propagate linkStatus to embedded frames that don't participate in
- // any of this part's links; otherwise their local link status takes precedence.
-
- FW_COrderedCollectionIterator iter(fContainerPart->GetShapeList());
- for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
- {
- if (shape->GetShapeType() == kProxyShape)
- {
- CProxyShape* proxyShape = (CProxyShape*)shape;
- if (!proxyShape->IsPublished() && !proxyShape->IsSubscribed())
- {
- FW_CProxyEmbeddedFrameIterator efiter(ev, proxyShape);
- for (ODFrame* embFrame = efiter.First(ev); efiter.IsNotComplete(ev); embFrame = efiter.Next(ev))
- embFrame->ChangeLinkStatus(ev, linkStatus);
- }
- }
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::DoUpdateLinks - Override
- //----------------------------------------------------------------------------------------
-
- void CContainerLinkManager::DoUpdateLinks(Environment* ev, ODFrame* odEmbeddedFrame, ODUpdateID change)
- {
- // Content displayed in the embedded frame has changed
-
- /* 1) If odEmbeddedFrame is involved in one of my link sources, update the link with new data.
- "If the part maintains the source of a link that includes the embedded frame, the
- part should update the link." (Recipe p.12) */
- if (this->CountPublishers(ev) > 0)
- {
- FW_CPartPublishIterator iter(fPart);
- for (CContainerPublishLink* publisher = (CContainerPublishLink*)iter.First(); iter.IsNotComplete();
- publisher = (CContainerPublishLink*)iter.Next())
- {
- if (publisher->HasEmbeddedFrame(ev, odEmbeddedFrame))
- {
- publisher->ContentUpdated(ev, change, FALSE);
- break;
- }
- }
- }
-
- /* 2) Call ContentUpdated on my display frames as appropriate */
- FW_CPartFrameIterator ite(fPart);
- for (FW_CFrame* frame = ite.First(); ite.IsNotComplete(); frame = ite.Next())
- {
- frame->GetODFrame(ev)->ContentUpdated(ev, change);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::CreateLink - Override
- //----------------------------------------------------------------------------------------
- ODLinkSource* CContainerLinkManager::CreateLink(Environment *ev, ODByteArray* data)
- {
- // CreateLink is overridden so that we can delete the pending publish link.
- // This prevents the link spec from being re-used to create more than one link.
-
- ODLinkSource* odLinkSource = FW_CLinkManager::CreateLink(ev, data);
- this->DeletePendingPublish(ev);
- return odLinkSource;
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::UndoPasteAs
- //----------------------------------------------------------------------------------------
- void CContainerLinkManager::UndoPasteAs(Environment* ev, CContainerSubscribeLink* link)
- {
- //--- Break the link ---
- this->BreakSubscribeLink(ev, link);
-
- //--- Remove subscribed shapes from the document ---
- this->DeleteSubscribedShapes(ev, link);
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::RedoPasteAs
- //----------------------------------------------------------------------------------------
- void CContainerLinkManager::RedoPasteAs(Environment* ev, CContainerSubscribeLink* link)
- {
- //-- Restore the broken link --
- this->RestoreSubscribeLink(ev, link);
-
- // When the restored link is updated, new subscriber shapes will be created
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::CommitUndone
- //----------------------------------------------------------------------------------------
- void CContainerLinkManager::CommitUndone(Environment* ev, CContainerSubscribeLink* link)
- {
- this->DeleteSubscribedShapes(ev, link);
- delete link;
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::DeleteSubscribedShapes
- //----------------------------------------------------------------------------------------
- void CContainerLinkManager::DeleteSubscribedShapes(Environment* ev, CContainerSubscribeLink* link)
- {
- this->SelectSubscribedShapes(ev, link);
- fContainerPart->fContainerSelection->DeleteSelection(ev);
- link->EmptyCollection(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::SelectSubscribedShapes
- //----------------------------------------------------------------------------------------
- void CContainerLinkManager::SelectSubscribedShapes(Environment* ev, CContainerSubscribeLink* link)
- {
- fContainerPart->fContainerSelection->CloseSelection(ev); // empty the selection
-
- // Saved link contains a list of the subscribed shapes
- FW_COrderedCollectionIterator iter(link->fCollection); /* PRIVATE */
- for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
- {
- fContainerPart->fContainerSelection->AddToSelection(ev, shape, FALSE);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::GetLatestSubscriber
- //----------------------------------------------------------------------------------------
- CContainerSubscribeLink* CContainerLinkManager::GetLatestSubscriber(Environment* ev)
- {
- // Return the most recent subscriber
- FW_CPartSubscribeIterator iter(fPart);
- return (CContainerSubscribeLink*) iter.Last();
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::RevealLink - Override
- //----------------------------------------------------------------------------------------
- void CContainerLinkManager::RevealLink(Environment *ev, ODLinkSource* linkSource)
- {
- CContainerPublishLink* sourceLink = (CContainerPublishLink*) ODtoPublishLink(ev, linkSource);
- if (sourceLink == NULL) return; // not our link!?
-
- // Choose a display frame for the source content
- FW_CFrame* frame = sourceLink->GetFrameToRevealLink(ev);
- if (frame)
- {
- // Ensure the display frame is revealed
- if (!frame->GetWindow(ev)->IsActive(ev))
- frame->GetWindow(ev)->Select(ev);
-
- // ----- Activate the frame -----
- if (!frame->IsActive(ev))
- {
- FW_CFrameFacetIterator iter(ev, frame); // find a facet
- frame->ActivateFrame(ev, iter.First(ev));
- }
-
- // Select the shape(s) that make up this link source
- sourceLink->DoSelect(ev, frame);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::ExternalizeLinks
- //----------------------------------------------------------------------------------------
-
- void CContainerLinkManager::ExternalizeLinks(Environment* ev, ODStorageUnit* su,
- FW_CCloneInfo* cloneInfo)
- {
- ODValueType containerPartValueType = fContainerPart->GetPartKind(ev);
-
- //--- Write out the source links ---
- if (this->CountPublishers(ev) > 0)
- {
- //-- Make sure the correct property and value is present in the SU --
- FW_SUForceFocus(ev, su, kContainerPropSourceLink, containerPartValueType);
-
- FW_CPartPublishIterator iter(fPart);
- for (CContainerPublishLink* slink = (CContainerPublishLink*)iter.First(); iter.IsNotComplete();
- slink = (CContainerPublishLink*)iter.Next())
- {
- slink->Externalize(ev, su, cloneInfo);
- }
- }
- else
- FW_SURemoveProperty(ev, su, kContainerPropSourceLink);
-
- //--- Write out the destination links ---
- if (this->CountSubscribers(ev) > 0)
- {
- //-- Make sure the correct property and value is present in the SU --
- FW_SUForceFocus(ev, su, kContainerPropDestLink, containerPartValueType);
-
- FW_CPartSubscribeIterator iter(fPart);
- for (CContainerSubscribeLink* link = (CContainerSubscribeLink*)iter.First(); iter.IsNotComplete();
- link = (CContainerSubscribeLink*)iter.Next())
- {
- link->Externalize(ev, su, cloneInfo);
- }
- }
- else
- FW_SURemoveProperty(ev, su, kContainerPropDestLink);
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::InternalizeLinks
- //----------------------------------------------------------------------------------------
-
- void CContainerLinkManager::InternalizeLinks(Environment* ev, ODStorageUnit* storageUnit)
- {
- ODValueType containerPartValueType = fContainerPart->GetPartKind(ev);
- unsigned long valueSize;
-
- if (storageUnit->Exists(ev, kContainerPropSourceLink, kODNULL, kODNULL))
- {
- storageUnit->Focus(ev, kContainerPropSourceLink, kODPosUndefined, containerPartValueType, 0, kODPosUndefined);
- valueSize = storageUnit->GetSize(ev);
- while (storageUnit->GetOffset(ev) < valueSize)
- {
- this->InternalizeOneSourceLink(ev, storageUnit);
- }
- }
-
- if (storageUnit->Exists(ev, kContainerPropDestLink, kODNULL, kODNULL))
- {
- storageUnit->Focus(ev, kContainerPropDestLink, kODPosUndefined, containerPartValueType, 0, kODPosUndefined);
- valueSize = storageUnit->GetSize(ev);
- while (storageUnit->GetOffset(ev) < valueSize)
- {
- this->InternalizeOneDestLink(ev, storageUnit);
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::GetSUValue
- //----------------------------------------------------------------------------------------
-
- ODULong CContainerLinkManager::GetSUValue(Environment* ev, ODStorageUnit* su,
- unsigned long size, void *buffer)
- {
- // Convenience function; also makes code easier to read
- FW_CByteArray ba;
- ODULong bytesRead = su->GetValue(ev, size, ba);
- ba.CopyBuffer(buffer, bytesRead);
-
- return bytesRead;
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::InternalizeOneDestLink
- //----------------------------------------------------------------------------------------
-
- void CContainerLinkManager::InternalizeOneDestLink(Environment* ev, ODStorageUnit* storageUnit)
- {
- //-- Storage unit must be focused to property kContainerPropDestLink, value containerPart kind
- ODStorageUnitRef suRef;
- ODLinkInfo linkInfo;
- ODDraft* suDraft = storageUnit->GetDraft(ev);
-
- GetSUValue(ev, storageUnit, kODStorageUnitRefSize, &suRef);
- if (storageUnit->IsValidStorageUnitRef(ev, suRef))
- {
- // We have a validated SU ref for the link, so read the link data
- ODLink* odLink = suDraft->AcquireLink(ev, storageUnit->GetIDFromStorageUnitRef(ev, suRef), NULL);
-
- //--- Read the link info and kind ---
- GetSUValue(ev, storageUnit, sizeof(ODLinkInfo), &linkInfo);
- // the length of the kind string was saved in the kind field
- ODType kind = (ODType) FW_CMemoryManager::AllocateBlock((ODULong)linkInfo.kind);
- GetSUValue(ev, storageUnit, (ODULong)linkInfo.kind, (void*)kind); // read the kind string
- linkInfo.kind = kind;
-
- //--- Create a subscriber object for this link ---
- CContainerSubscribeLink* destLink = new CContainerSubscribeLink(ev, odLink, fContainerPart->GetMainPresentation(), fContainerPart->fContainerSelection, &linkInfo);
-
- //--- Read the number of shapes in the link ---
- unsigned long shapeCount;
- GetSUValue(ev, storageUnit, sizeof(unsigned long), &shapeCount);
-
- //--- Read each shape index and add the shape to the source link ---
- short extIndex;
- while (shapeCount > 0)
- {
- GetSUValue(ev, storageUnit, sizeof(short), &extIndex);
- CBaseShape* shape = fContainerPart->FindShapeWithIndex(extIndex);
- if (shape)
- destLink->AddShape(ev, shape);
- shapeCount--;
- }
-
- //--- Finish subscribing ---
- this->AddToSubscribeLinkList(ev, destLink);
- destLink->HandleSubscribe(ev);
- odLink->Release(ev); // to balance AcquireLink above
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::InternalizeOneSourceLink
- //----------------------------------------------------------------------------------------
-
- void CContainerLinkManager::InternalizeOneSourceLink(Environment* ev, ODStorageUnit* storageUnit)
- {
- //-- Storage unit must be focused to property kContainerPropSourceLink, value containerPart kind
- ODStorageUnitRef suRef;
- ODUpdateID updateID;
- ODDraft* suDraft = storageUnit->GetDraft(ev);
-
- GetSUValue(ev, storageUnit, kODStorageUnitRefSize, &suRef);
- if (storageUnit->IsValidStorageUnitRef(ev, suRef))
- {
- // We have a validated SU ref for the link, so read the link source data
- ODLinkSource* odLinkSource = suDraft->AcquireLinkSource(ev, storageUnit->GetIDFromStorageUnitRef(ev, suRef));
- GetSUValue(ev, storageUnit, sizeof(ODUpdateID), &updateID);
-
- //--- Create a publish object for this source link ---
- CContainerPublishLink* sourceLink = new CContainerPublishLink(ev, updateID, fContainerPart->GetMainPresentation(), fContainerPart->fContainerSelection, FALSE);
-
- //--- Read the number of shapes in the link ---
- unsigned long shapeCount;
- GetSUValue(ev, storageUnit, sizeof(unsigned long), &shapeCount);
-
- //--- Read each shape index and add the shape to the source link ---
- short extIndex;
- while (shapeCount > 0)
- {
- GetSUValue(ev, storageUnit, sizeof(short), &extIndex);
- CBaseShape* shape = fContainerPart->FindShapeWithIndex(extIndex);
- if (shape)
- sourceLink->AddShape(ev, shape);
- shapeCount--;
- }
-
- //--- Make this publisher official ---
- sourceLink->SetODLinkSource(ev, odLinkSource);
- this->AddToPublishLinkList(ev, sourceLink);
- odLinkSource->Release(ev); // to balance AcquireLinkSource above
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CContainerLinkManager::RegisterSubscribers
- //----------------------------------------------------------------------------------------
- void CContainerLinkManager::RegisterSubscribers(Environment* ev)
- {
- if (this->CountSubscribers(ev) > 0)
- {
- FW_CPartSubscribeIterator iter(fPart);
- for (CContainerSubscribeLink* link = (CContainerSubscribeLink*)iter.First(); iter.IsNotComplete(); link = (CContainerSubscribeLink*)iter.Next())
- {
- link->Register(ev, fPart); // auto-update link will have its LinkUpdated method called
- }
- }
- }
-